<?php
namespace App\Common\Services;


use AlibabaCloud\Client\Exception\ClientException;
use App\Common\Models\ComEmailCodeModel;
use App\Exceptions\ApiException;
use App\Services\CommonService;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

class ComEmailCodeService extends CommonService
{
    protected $cache = true;

    protected $cacheBucket = 'ComEmailCode:';

    /**
     * LogSendCodeService constructor.
     * @param ComEmailCodeModel $model
     */
    public function __construct(ComEmailCodeModel $model)
    {
        $this->model = $model;
    }

    /**
     * 发送验证码
     * @param array $params phone email type 验证类型 0 手机验证 1邮箱验证
     * @return bool|mixed
     * @throws \App\Exceptions\ApiException;
     * @throws ClientException
     */
    public function sendValidateCode($email,$isSend=true,$language='zh-cn',$footer='')
    {
        $resultData=['id'=>0,'code'=>''];
        $code = mt_rand(100000, 999999);
        $resultData['code']=$code;
        $currentTime = time(); //当前时间
        $title='邮箱验证码';//邮件标题
        if(empty($email)){
            throw new ApiException(10021);
        }
        if($isSend){
            $httpData=[];//邮件内容变量参数
            $httpData['email']=$email;
            $httpData['code']=$code;
            $httpData['footer']=$footer;
            $mailTemp='mail.validateCodeModel';
            if($language=='en-us'){
                $mailTemp= 'mail.en.validateCodeModel';
            }
            Mail::send($mailTemp, $httpData, function ($message) use ($email,$title) {
                $message->to($email)->subject($title);
            });
        }
        $data = [
            'email' => $email,
            'code' => $code,
            'error' => '',
        ];
        $data['status'] = 1;
        $data['expire_time']=$currentTime + config('cache.sms_time');
        $key=$email;
        $cacheKey=md5($key);
        $cacheTime=config('cache.sms_time');
        $this->setCacheData($cacheKey,$data,$cacheTime);
        $logId = $this->saveLogSendCode($data);
        $resultData['id']=$logId;
        $resultData['code']=$code;
        $resultData['email']=$email;
        return  $resultData;

    }


    /**
     * 短信记录
     * @param array $params 短信存储参数
     * @return bool|mixed
     * @throws App\Base\Exceptions\ApiException
     */
    public function saveLogSendCode($params = [])
    {
        //手机验证码信息
        $nowTime=nowTime();
        $codeData = [
            'code' => $params['code'],
            'email' =>empty($params['email']) ? '' : $params['email'],
            'status' => $params['status'],
            'error' => empty($params['error']) ? '' : $params['error'],
            'create_time' => $nowTime
        ];
        if(!empty($params['expire_time'])){
            $codeData['expire_time']= date('Y-m-d H:i:s', $params['expire_time']);
        }
        try {
            $id=$this->model->insertGetId($codeData);
            if (!$id) {
                Log::info('method:saveLogSendCode:保存验证码失败');
                throw new ApiException(500);
            }
            return $id;
        } catch (QueryException $ex) {
            //异常处理
            Log::info('method:saveLogSendCode:' . $ex->getMessage());
            Log::info('method:saveLogSendCode:' . $ex->getTraceAsString());
            throw new ApiException('common.server_busy', '服务器忙，请稍候重试~');
        }
    }

    /**
     * 校验短信验证码是否有效
     * @param string $key 手机号/邮箱
     * @param string $code 验证码
     * @param integer $type 验证类型 0 手机验证 1邮箱验证
     * @return array  -1 失败重新获取验证码 -2验证码错误重新输入，1 成功是否验证成功
     */
    public  function validateCode($key, $code)
    {
        //todo 通过redis 缓存来验证
        $result=['code'=>-1];
        $current_time = time();
        $cacheKey=md5($key);
        $cacheData=$this->getCacheData($cacheKey);
        if($cacheData){
            if(!empty($cacheData['expire_time'])&&$cacheData['expire_time']>$current_time&&$code==$cacheData['code']){
                $result['code']=1;
                $this->removeByKey($cacheKey);
            }else if($code!=$cacheData['code']){
                $result['code']=-2;
            }
        }
        return $result;
    }

    /**
     * 校验短信验证码一分钟内是否重复发送
     * */
    public function validatePhoneMinute($phone){
        $result=['code'=>0];
        $where=[
            'phone' => $phone,
            'status' => 1,
        ];
        $smsTime= config('cache.sms_time');
        $addTime=($smsTime/60)-1;
        $expireTime = date("Y-m-d H:i:s",strtotime("+".$addTime." minute",strtotime(nowTime()))); // 短信有效时间为30分钟。，当前时间+29
        $smsData = $this->model->where($where)->where('expire_time','>',$expireTime)->first();
        if(!empty($smsData)){
            $result['code']=-1;
        }
        return $result;
    }


    /**
     * 通用缓存方法
     * @param string $key
     * @param array $data
     * */
    public function setCacheData($key, $data,$cacheTime=0)
    {
        $cacheTime=empty($cacheTime)?config('cache.def_time'):$cacheTime;
        Cache::put($this->getCacheKey($key), $data, $cacheTime);
    }


    /**
     * 获取通用缓存数据key
     * @param string $key
     * @return string
     * */
    private function getCacheKey($key)
    {
        $prefix='VERIFICATION';
        return $this->cacheBucket.$prefix.$key;
    }

    /**
     * 通用缓存方法
     * @param string $key
     * @param array $data
     * */
    public function getCacheData($key)
    {
        $dataKey= $this->getCacheKey($key);
        return Cache::get($dataKey);
    }
}
